package com.alex.j2se.stream;

import java.util.function.Function;
import java.util.stream.LongStream;
import java.util.stream.Stream;

public class parallelStreamPerfTest {
    public static long measureSumPerf(Function<Long, Long> adder, long n) {
        long fastest = Long.MAX_VALUE;
        for (int i = 0; i < 10; i++) {
            long start = System.nanoTime();
            long sum = adder.apply(n);
            long duration = (System.nanoTime() - start) / 1_000_000;
            System.out.println("Result: " + sum);
            if (duration < fastest) fastest = duration;
        }
        return fastest;
    }

    public static long sequentialSum(long n) {
        return Stream.iterate(1L, i -> i + 1)
                .limit(n)
                .reduce(0L, Long::sum);
    }

    public static long parallelSum(long n) {
        return Stream.iterate(1L, i -> i + 1)
                .limit(n).parallel()
                .reduce(0L, Long::sum);
    }

    public static long parallelRangedSum(long n) {
        return LongStream.rangeClosed(1, n)
                .parallel()
                .reduce(0L, Long::sum);
    }


    public static void sequentialSumTest() {
        System.out.println("Sequential sum done in:" + measureSumPerf(parallelStreamPerfTest::sequentialSum, 10_000_000) + " msecs");
    }

    public static void parallelSumTest() {
        System.out.println("Parallel sum done in:" + measureSumPerf(parallelStreamPerfTest::parallelSum, 10_000_000) + " msecs");
    }

    public static void parallelRangedSumTest() {
        System.out.println("parallelRanged sum done in:" + measureSumPerf(parallelStreamPerfTest::parallelRangedSum, 10_000_000) + " msecs");
    }

    public static void main(String[] args) {
//        sequentialSumTest();//Sequential sum done in:106 msecs
//        parallelSumTest();//Parallel sum done in:173 msecs
        parallelRangedSumTest();//parallelRanged sum done in:1 msecs
    }
}
